﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Windows8Accelerator.Core.Xaml.Storage;

namespace Windows8Accelerator.Core.Xaml.Helpers
{
    public static class AssemblyHelper
    {
        private static Assembly _ExecutingAssembly;
        public static async Task<Assembly> GetExecutingAssemblyAsync()
        {
            if (_ExecutingAssembly == null)
            {
                var files = await StorageHelperBase.Instance.GetFilesAsync(StorageLocation.InstalledLocation);
                var exe = files.Where((f) => f.Name.EndsWith(".exe")).FirstOrDefault();
                if (exe == null)
                {
                    using (var xmlReader = XmlReader.Create(await StorageHelperBase.Instance.OpenFileReadAsync("AppManifest.xaml", StorageLocation.InstalledLocation)))
                    {
                        xmlReader.MoveToContent();
                        var entryPointAssembly = xmlReader.GetAttribute("EntryPointAssembly");
                        exe = files.Where((f) => f.Name.Equals(entryPointAssembly + ".dll")).FirstOrDefault();
                    }
                }
                _ExecutingAssembly = Assembly.Load(new AssemblyName() { Name = Path.GetFileNameWithoutExtension(exe.Name) });
            }
            return _ExecutingAssembly;
        }

        private static Dictionary<string, Type> _TypesByName;

        public static async Task<Type> GetTypeAsync(string typeName)
        {
            if (_TypesByName == null)
            {
                var typesByName = new Dictionary<string, Type>();
                var executingAssembly = await GetExecutingAssemblyAsync();
                foreach (var type in executingAssembly.GetTypes())
                {
                    typesByName[type.Name] = type;
                    typesByName[type.FullName] = type;
                }
                _TypesByName = typesByName;
            }
            if (_TypesByName.ContainsKey(typeName))
                return _TypesByName[typeName];
            return null;
        }

        private static Assembly _Windows8AcceleratorAssembly;

        public static T CreateInstanceOfAccelerator<T>()
            where T : class
        {
            var typeInfo = typeof(T);
            foreach (var type in GetWindows8AcceleratorAssembly().GetTypes())
            {
                if (typeInfo.IsAssignableFrom(type) && typeInfo != type)
                    return (T)Activator.CreateInstance(type);
            }
            return null;
        }

        private static Assembly GetWindows8AcceleratorAssembly()
        {
            return Assembly.GetExecutingAssembly();
            if (_Windows8AcceleratorAssembly == null)
                _Windows8AcceleratorAssembly = Assembly.Load(new AssemblyName() { Name = "W8A.WP7.C.X" });
            return _Windows8AcceleratorAssembly;
        }
    }
}
